﻿using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.SystemFacade;
using Fuse8.ContentManagementFramework.SystemFacade.Utilities;
using Fuse8.ContentManagementFramework.Web.MvcPowered;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;

namespace Fuse8.ContentManagementFramework.Web.ApplicationRuntime
{
    public class MediaFileHandler
    {
        private HttpContextBase _httpContext;

        public MediaFileHandler(HttpContextBase httpContext)
        {
            Guard.ArgumentNotNull(httpContext, "httpContext");

            _httpContext = httpContext;
        }

        public ActionResult GetMediaFile(int mediaId, int? width, int? height, string crop)
        {
            ActionResult result = null;

            if (mediaId > 0)
            {
                var mediaFile = new CmsMediaFileService().FindOne(mediaId);

                if (mediaFile != null)
                {
                    result = GetMediaFile(mediaFile.LinkedFileName, mediaFile.OriginalFileName, mediaFile.ContentType, width, height, crop, mediaId, mediaFile.BlockFromSearchEngines);
                }
            }

            return result ?? new HttpNotFoundResult();
        }

        public virtual ActionResult GetMediaFile(string fileName, string originalFileName, string contentType, int? width, int? height, string crop, int mediaId = 0, bool blockFromSearchEngines = false)
        {
            ActionResult result = null;

            if (!string.IsNullOrEmpty(fileName))
            {
                var filePath = Path.Combine(_httpContext.Server.MapPath(CmsConfiguration.AssetUploadPath), fileName);

                if (File.Exists(filePath))
                {
                    result = GetMedia(filePath, originalFileName, contentType, width, height, crop, mediaId, blockFromSearchEngines);
                }
            }

            return result ?? GetDefaultMedia(width, height);
        }

        protected virtual ActionResult GetDefaultMedia(int? width, int? height)
        {
            var defaultImagePath = _httpContext.Server.MapPath(
                string.Format("{0}/{1}", CmsConfiguration.AssetUploadPath, CmsConfiguration.DefaultImagePath));

            return GetMedia(defaultImagePath, Path.GetFileName(defaultImagePath), null, width, height, null);
        }

        protected virtual ActionResult GetMedia(string filePath, string downLoadedFileName, string contentType, int? width, int? height, string crop, int mediaId = 0, bool blockFromSearchEngines = false)
        {
            ActionResult result = null;

            try
            {
                if (height.HasValue || width.HasValue)
                {
                    bool isExisting;

                    filePath = ImageResizer.GetOrResize(filePath, height.HasValue ? height.Value : Int32.MaxValue, width.HasValue ? width.Value : Int32.MaxValue, crop, out isExisting);

                    if (isExisting)
                    {
                        result = new CmsMediaFileActionResult(_httpContext, mediaId, filePath, downLoadedFileName,
                                                              width, height, contentType) { BlockFromSearchEngines = blockFromSearchEngines };
                    }
                }
                else
                {
                    result = new CmsMediaFileActionResult(_httpContext, mediaId, filePath, downLoadedFileName, width, height, contentType)
                                 {
                                     BlockFromSearchEngines = blockFromSearchEngines
                                 };
                }
            }
            catch
            {
                //TO DO: log
            }

            return result ?? new HttpNotFoundResult();
        }
    }

    public abstract class CmsBaseApplicationController : PageNotFoundHandledController
    {
        #region View methods

        public virtual ActionResult GetMediaContentByCode(string code, int? width, int? height)
        {
            return null;
        }

        public virtual ActionResult GetMediaFileById(int id, int? w, int? h, string crop = "")
        {
            return new MediaFileHandler(HttpContext).GetMediaFile(id, w, h, crop);
        }

        public virtual ActionResult GetMediaFile(string fileName, string originalFileName, string contentType, int? w, int? h)
        {
            return new MediaFileHandler(HttpContext).GetMediaFile(fileName, originalFileName, contentType, w, h, "");
        }

        public virtual void DeleteMediaFile(string originalFileName)
        {
            Guard.ArgumentNotEmpty(originalFileName, "originalFileName");

            var filesToRemove = Directory.EnumerateFiles(HttpContext.Server.MapPath(CmsConfiguration.AssetUploadPath), originalFileName, SearchOption.AllDirectories);
            foreach (var item in filesToRemove)
            {
                System.IO.File.Delete(item);
            }
        }        
        #endregion View methods
    }

    public abstract class PageNotFoundHandledController : Controller
    {
        protected internal ActionResult Prepare404View()
        {
            ControllerContext.HttpContext.Response.StatusCode = 404;
            ControllerContext.HttpContext.Response.Status = "404 Not Found";

            ActionResult result = View("404");
            if (!Request.IsAjaxRequest())
            {
                var cmsContext = DependencyServiceLocator.Current.GetInstance<ICmsContext>();
                if (!cmsContext.IsInAdministrationArea)
                {
                    //todo: replace with getting page by special code
                    var page = new CmsPageService().GetPageByUrl("/404");

                    if (page != null)
                    {
                        cmsContext.ContextPage = page;
                        result = new CmsViewResult()
                        {
                            TemplateType = page.Template.TemplateType,
                            ViewName = page.PageName,
                            MasterName = page.Template.TemplateUrl,
                            ViewData = ViewData,
                            TempData = TempData
                        };
                    }
                }
            }
            else
            {
                result = PartialView("404Partial");
            }

            return result;
        }

        protected override void HandleUnknownAction(string actionName)
        {
            Prepare404View().ExecuteResult(ControllerContext);
        }
    }
}